package mysql_init

import (
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
	"go_server/login_server/util"
	"go_server/zinx/zlog"
	"go_server/zinx/zutils"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	ormlog "gorm.io/gorm/logger"
	"log"
	"os"
	"time"
)

var (
	login_mysql_viper *viper.Viper
	login_mysql_log ormlog.Interface
	login_mysql *gorm.DB

	maxOpenConns = 200
	maxIdleConns = 20
)

func Init() {
	login_mysql_viper, _ = util.CreateConfig("mysql")
	login_mysql_viper.WatchConfig()

	slowTime := login_mysql_viper.GetInt64("slow_sql_mills")
	logLevel := login_mysql_viper.GetInt("log_level")
	login_mysql_log = zutils.LogNew(log.New(os.Stdout, "\r\n", log.LstdFlags),
		ormlog.Config{
			SlowThreshold: time.Duration(slowTime) * time.Millisecond,
			Colorful:      true,
			LogLevel: ormlog.LogLevel(logLevel),
		})

	dbName := login_mysql_viper.GetString("database")
	host := login_mysql_viper.GetString("host")
	port := login_mysql_viper.GetInt("port")
	user := login_mysql_viper.GetString("username")
	pass := login_mysql_viper.GetString("password")

	login_mysql = createMysqlDB(dbName, host, user, pass, port)

	login_mysql_viper.OnConfigChange(func(in fsnotify.Event) {
		changeSlowTime := login_mysql_viper.GetInt64("slow_sql_mills")
		if changeSlowTime != slowTime {
			(login_mysql.Logger.(*zutils.Gormlogger)).SetSlowThreshold(changeSlowTime)
			slowTime = changeSlowTime
		}

		changeLogLevel := login_mysql_viper.GetInt("log_level")
		if changeLogLevel != logLevel {
			(login_mysql.Logger.(*zutils.Gormlogger)).SetLogLevel(ormlog.LogLevel(changeLogLevel))
			logLevel = changeLogLevel
		}

		changeMaxOpenConns := login_mysql_viper.GetInt("max_open_conns")
		if changeMaxOpenConns != maxOpenConns {
			sqlDB, _ := login_mysql.DB()
			sqlDB.SetMaxOpenConns(changeMaxOpenConns)
			maxOpenConns = changeMaxOpenConns
		}

		changeMaxIdleConns := login_mysql_viper.GetInt("max_idle_conns")
		if changeMaxIdleConns != maxIdleConns {
			sqlDB, _ := login_mysql.DB()
			sqlDB.SetMaxIdleConns(changeMaxIdleConns)
			maxIdleConns = changeMaxIdleConns
		}
	})
}

func GetServerDBConnection() *gorm.DB {
	return login_mysql
}

func createMysqlDB(dbName, host, user, pass string, port int) *gorm.DB {
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=true", user, pass, host, port, dbName)
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		SkipDefaultTransaction:                   true,
		Logger:                                   login_mysql_log,
		PrepareStmt:                              true,
	})
	if err != nil {
		zlog.Panicf("连接到数据库出错！！！dsn %s err: %v", dsn, err)
	}

	sqlDB, err := db.DB()
	if err != nil {
		zlog.Panicf("获取数据库句柄出错！！！ dsn %s err: %v", dsn, err)
	}

	if login_mysql_viper.IsSet("max_open_conns") {
		maxOpenConns = login_mysql_viper.GetInt("max_open_conns")
	}
	sqlDB.SetMaxOpenConns(maxOpenConns)

	if login_mysql_viper.IsSet("max_idle_conns") {
		maxIdleConns = login_mysql_viper.GetInt("max_idle_conns")
	}
	sqlDB.SetMaxIdleConns(maxIdleConns)

	zlog.Infof("connect to mysql db %s success!!!", dbName)
	return db
}